home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / inventor / sharedSV / SceneViewer.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  13.5 KB  |  525 lines

  1. /*
  2.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  */
  20.  
  21. //
  22. //  Sample SceneViewer program.
  23. //   This program reads in a Inventor datafile, and creates a SceneViewer
  24. //   to allow interaction with it.
  25. //
  26.  
  27. #include <X11/Intrinsic.h>
  28. #include <X11/keysym.h>
  29.  
  30. #include <Inventor/SoBaseKit.h>
  31. #include <Inventor/SoDB.h>
  32. #include <Inventor/SoInteraction.h>
  33. #include <Inventor/SoNodeKit.h>
  34. #include <Inventor/SoSelection.h>
  35. #include <Inventor/SoXt.h>
  36. #include <Inventor/SoSensor.h>
  37. #include <Inventor/SbTime.h>
  38.  
  39. #include "SoSceneViewer.h"
  40. #include "Common.h"
  41. #include <limits.h>
  42. #include <sys/types.h>
  43. #include <sys/prctl.h>
  44. #include <sys/schedctl.h>
  45. #include <sys/stat.h>
  46. #include <fcntl.h>
  47. #include <stdlib.h>
  48. #include <getopt.h>
  49. #include <string.h>
  50. #include <stdio.h>
  51. #include <time.h>
  52. #include <unistd.h>
  53. #include <sys/types.h>
  54. #include <sys/socket.h>
  55. #include <netinet/in.h>
  56. #include <net/if.h>
  57. #include <sys/ioctl.h>
  58. #include <net/soioctl.h>
  59. #include <arpa/inet.h>
  60. #include "multicast.h"
  61.  
  62. //
  63. //  The following is used by printScreen
  64. //
  65. extern "C" {
  66. struct IMAGE;
  67. #define IMAGIC  0732
  68.  
  69. /* colormap of images */
  70. #define CM_NORMAL               0       /* file contains rows of values which 
  71.                                          * are either RGB values (zsize == 3) 
  72.                                          * or greyramp values (zsize == 1) */
  73. #define CM_DITHERED             1
  74. #define CM_SCREEN               2       /* file contains data which is a screen
  75.                                          * image; getrow returns buffer which 
  76.                                          * can be displayed directly with 
  77.                                          * writepixels */
  78. #define CM_COLORMAP             3       /* a colormap file */
  79.  
  80. #define TYPEMASK                0xff00
  81. #define BPPMASK                 0x00ff
  82. #define ITYPE_VERBATIM          0x0000
  83. #define ITYPE_RLE               0x0100
  84. #define ISRLE(type)             (((type) & 0xff00) == ITYPE_RLE)
  85. #define ISVERBATIM(type)        (((type) & 0xff00) == ITYPE_VERBATIM)
  86. #define BPP(type)               ((type) & BPPMASK)
  87. #define RLE(bpp)                (ITYPE_RLE | (bpp))
  88. #define VERBATIM(bpp)           (ITYPE_VERBATIM | (bpp))
  89. #define IBUFSIZE(pixels)        ((pixels+(pixels>>6))<<2)
  90. #define RLE_NOP                 0x00
  91.  
  92. #define ierror(p)               (((p)->flags&_IOERR)!=0)
  93. #define ifileno(p)              ((p)->file)
  94. #define getpix(p)               (--(p)->cnt>=0 ? *(p)->ptr++ : ifilbuf(p))
  95. #define putpix(p,x)             (--(p)->cnt>=0 \
  96.                                     ? ((int)(*(p)->ptr++=(unsigned)(x))) \
  97.                                     : iflsbuf(p,(unsigned)(x)))
  98.  
  99.  
  100. extern IMAGE *iopen( char *, char *, unsigned int, unsigned int, unsigned int, unsigned, unsigned int );
  101. extern int   iclose( IMAGE * );
  102. extern int   putrow( IMAGE *, unsigned short *, unsigned int, unsigned int );
  103. extern int   cpacktorgb( unsigned long *, unsigned short *, unsigned short *, unsigned short *, int );
  104. int ioctl(int fildes, int request, ... ) ;
  105. }
  106.  
  107.  
  108.  
  109.  
  110. extern int timerflag;
  111. extern void myreadcallback(void *, SoSensor *);
  112. extern void mywritecallback(void *, SoSensor *);
  113. SoSceneViewer *mysv;
  114. SoDataSensor *envirosensor;
  115. SoTimerSensor *timersensor;
  116. extern SoWriteAction nwa;
  117.     struct sockaddr_in  inaddr,outaddr;
  118.     int                 inaddrlen,outaddrlen, infd, outfd, cnt, i;
  119.     struct ip_mreq      mreq;
  120.     char                *group = EXAMPLE_GROUP;
  121.     u_short             port = EXAMPLE_PORT;
  122.     u_char              ttl = EXAMPLE_TTL;
  123.     int                 send_mode = 1;
  124.     int                 iflag = 0;
  125.     char                *interface;
  126.     struct in_addr      ifaddr;
  127.     struct in_addr      grpaddr;
  128.  
  129.  
  130.  
  131.  
  132.  
  133. void
  134. printScreen( SoSceneViewer *sv)
  135. {
  136.         unsigned long *rgbArray;
  137.         short      numRows, numColumns;
  138.         IMAGE       *oimage;
  139.         int       writeerr, y;
  140.         unsigned long *ss;
  141.         unsigned short *rs, *gs, *bs;
  142.  
  143.         //
  144.         // Grabs screen and saves in an .rgb file
  145.         // (this code was stolen from 4Dgifts/scrsave.c.)
  146.         //
  147.         printf("Grabbing screen...");
  148.             rgbArray = sv->copyScreen( numRows, numColumns );
  149.  
  150.         // open the image file
  151.         oimage = iopen( "/usr/tmp/inventor.rgb", "w", RLE(1), 3,
  152.             numColumns, numRows, 3 );
  153.         writeerr = 0;
  154.  
  155.         // malloc buffers
  156.         rs = (unsigned short *)malloc(numColumns*sizeof(short));
  157.         gs = (unsigned short *)malloc(numColumns*sizeof(short));
  158.         bs = (unsigned short *)malloc(numColumns*sizeof(short));
  159.  
  160.         // write the data to the image file
  161.         ss = rgbArray;
  162.         for( y = 0; y < numRows; y++ ) {
  163.         cpacktorgb( ss, rs, gs, bs, numColumns );
  164.         if( putrow( oimage, rs, y ,0 ) != numColumns)
  165.             writeerr = 1;
  166.         if( putrow( oimage, gs, y, 1 ) != numColumns)
  167.             writeerr = 1;
  168.         if( putrow( oimage, bs, y, 2 ) != numColumns)
  169.             writeerr = 1;
  170.         ss += numColumns;
  171.         }
  172.  
  173.         // free buffers
  174.         free(rs);
  175.         free(gs);
  176.         free(bs);
  177.  
  178.         // close the image file
  179.         if( iclose( oimage ) < 0 )
  180.         writeerr = 1;
  181.  
  182.         // exit with a bad status on write error
  183.         if (writeerr == 1)  {
  184.         fprintf( stderr, "ERROR: image file write error!\n" );
  185.         exit(1);
  186.         }
  187.         printf("...done. (see /usr/tmp/inventor.rgb)\n");
  188.         ////////////////////////////////////////////////////////////
  189.         // end of scrsave.c stolen code
  190.         ////////////////////////////////////////////////////////////
  191. }
  192.  
  193. static SbBool
  194. getArgs(int argc, char **argv, char *&envFile, char *&filename)
  195. {
  196.     SbBool ok = TRUE;
  197.     
  198.     envFile = NULL;
  199.     filename = NULL;
  200.  
  201.     if (argc == 2) {
  202.     filename = argv[1];
  203.     }
  204.     else if (argc > 2) {
  205.         // see if there is a -e before the file name
  206.         if (strcmp(argv[1], "-p") == 0) {
  207.         port = (u_short)atoi(argv[2]);
  208.         if (argc > 3)
  209.             filename = argv[3];
  210.     }
  211.     else if (argc == 4) {
  212.         // maybe the -e is after the file name
  213.         if (strcmp(argv[2], "-p") == 0) {
  214.         port = (u_short)atoi(argv[3]);
  215.         filename = argv[1];
  216.         }
  217.     }
  218.     else ok = FALSE;
  219.     }
  220.     return ok;
  221. }
  222.  
  223. void
  224. SoXtFullViewer::viewingToggleCB(void *v, SbBool flag)
  225. {
  226.  ((SoXtFullViewer *)v)->setViewing(flag);
  227.         if(! mysv->isViewing())
  228.           {
  229. #ifdef MYDEBUG
  230.             printf("TIMER OFF, from pick menu\n");
  231. #endif
  232.             timersensor->unschedule();
  233.             timerflag=0;
  234.           }
  235.         else
  236.           {
  237. #ifdef MYDEBUG
  238.             printf("TIMER ON, from pick menu\n");
  239. #endif
  240.             timersensor->schedule(SbTime((unsigned long)DATATIME));
  241.             timerflag=1;
  242.  
  243.           }
  244.  
  245.  }
  246.  
  247.  
  248.  
  249. void main(int argc, char **argv)
  250. {
  251.     Widget         mainWindow;
  252.     SoSceneViewer    *sv;
  253.     SoInput        in;
  254.     char        *envFile, *filename;
  255.  
  256.     // check usage
  257.     if (! getArgs(argc, argv, envFile, filename )) {
  258.     fprintf(stderr, "usage:  SharedSV [-p port_number] [file.iv]\n");
  259.     exit( 1 );
  260.     }
  261.  
  262.     
  263.  
  264.     // init Inventor
  265.     mainWindow = SoXt::init(argv[0]);
  266.  
  267.    // init commsstuff
  268.   infd=openMulticastSocket(&inaddr,1,0,EXAMPLE_GROUP,NULL,"r");
  269.   outfd=openMulticastSocket(&outaddr,1,0,EXAMPLE_GROUP,NULL,"w");
  270. // Turn on non-blocking I/O
  271.   if( fcntl( infd, F_SETFL, FNDELAY ) < 0 ) {
  272.        perror( "fcntl F_SETFL, FNDELAY" ) ;
  273.    }
  274.  
  275.  
  276. #ifdef MYDEBUG
  277.   printf("infd=%d, outfd=%d\n",infd,outfd);
  278. #endif
  279.  
  280.   outaddrlen=sizeof(outaddr);
  281.   inaddrlen=sizeof(inaddr);
  282.  
  283.      
  284.     
  285.     // read the file in, creating a selection node as the root
  286.     // of the scene graph.
  287.     SoSelection *selRoot = new SoSelection;
  288.     selRoot->ref();
  289.     if (filename != NULL && in.openFile(filename) ) {
  290.     
  291.     fprintf( stderr, "Reading input file...");
  292.     SoNode *n;
  293.     while ((SoDB::read(&in, n) != FALSE) && (n != NULL))
  294.         selRoot->addChild(n);
  295.     
  296.     if ( selRoot->getNumChildren() == 0 )
  297.         fprintf(stderr, "No data read; creating empty scene.\n" );
  298.     else
  299.         fprintf(stderr, "done.\n");
  300.     }
  301.  
  302.     //
  303.     // Create the SceneViewer
  304.     //
  305.     mysv = sv = new SoSceneViewer(selRoot, envFile);
  306.     selRoot->unref();
  307.     
  308.     // The typeIds in this list specify which node types (and subclasses
  309.     // of those types) are candidates for selection. In this case,
  310.     // we want node kits to be selected (SoBaseKit and its subclasses).
  311.     SoTypeList *priorities = selRoot->getSelectTypePriorityList();
  312.     if ( priorities )
  313.     priorities->insert( SoBaseKit::getClassTypeId(), 0 );
  314. //
  315. // added by smf
  316. #ifdef MYDEBUG
  317.   printf("TIMER ON\n");
  318. #endif
  319.     timersensor = new SoTimerSensor(myreadcallback,(void *) NULL);
  320.     timersensor->schedule(SbTime((unsigned long)DATATIME));
  321.  
  322.     //
  323.     // Build and show the SceneViewer
  324.     //
  325.     sv->build(mainWindow);
  326.     sv->show();
  327.     XtRealizeWidget(mainWindow);
  328.  
  329.     // add an event handler for the print screen key test
  330. //    Widget w = sv->getWidget();
  331.  //   XtAddEventHandler(w, KeyPressMask, False,
  332. ////        (XtEventHandler) printScreen,
  333. //        (XtPointer) sv);
  334.  
  335. // added by smf
  336.  
  337. #ifdef MYDEBUG
  338.   printf("ENVIRO ON\n");
  339. #endif
  340.     envirosensor = new SoDataSensor(mywritecallback,(void *)NULL);
  341.     envirosensor->attach(mysv->lightsCameraEnvironment);
  342.     //
  343.     // Loop forever
  344.     //
  345.     SoXt::mainLoop();
  346. }
  347.  
  348.  
  349.  
  350.  
  351. /* BEGIN PROTOTYPES -S multicast.c */
  352. static int  checkInterface( const char *interface, int fd, char mode,
  353.                 struct in_addr *ifaddr ) ;
  354. /* END PROTOTYPES -S multicast.c */
  355.  
  356.  
  357. int openMulticastSocket(
  358.     struct sockaddr_in *addr,
  359. //    u_short port,
  360.     u_char ttl,
  361.     u_char loop,
  362.     const char *group,
  363.     const char *interface,
  364.     const char *mode_str
  365.     )
  366. {
  367.     int                fd ;
  368.     int                st ;
  369.     int                on;
  370.     char            mode = tolower( *mode_str ) ;
  371.     struct in_addr    ifaddr;
  372.     struct in_addr    grpaddr;
  373.     struct ip_mreq    mreq;
  374.  
  375.     grpaddr.s_addr = inet_addr( group ) ;
  376.     if( !IN_MULTICAST( grpaddr.s_addr ) ) {
  377.         fprintf( stderr, "Invalid multicast group address: %s\n", group ) ;
  378.         return( -1 ) ;
  379.         }
  380.  
  381.     if( strlen( mode_str ) != 1 || ( mode != 'r' && mode != 'w' ) ) {
  382.         fprintf( stderr, "openMulticastSocket: improper mode `%s'\n",
  383.                     mode_str ) ;
  384.         return( -1 ) ;
  385.         }
  386.  
  387.     fd = socket( AF_INET, SOCK_DGRAM, 0 ) ;
  388.     if( fd < 0 ) {
  389.         perror( "socket" ) ;
  390.         return( fd ) ;
  391.         }
  392.  
  393.     bzero( addr, sizeof( *addr ) ) ;
  394.     addr->sin_family = AF_INET ;
  395.     addr->sin_addr.s_addr = INADDR_ANY ;
  396.     addr->sin_port = htons( port ) ;
  397.  
  398.     ifaddr.s_addr = INADDR_ANY;
  399.  
  400.     if( interface != NULL ) {
  401.         if( ( st = checkInterface( interface, fd, mode, &ifaddr ) ) < 0 ) {
  402.             close( fd ) ;
  403.             return( st ) ;
  404.             }
  405.         }
  406.  
  407.     switch( mode ) {
  408.  
  409.         case 'w' :
  410.             if( setsockopt( fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
  411.                             sizeof(ttl) ) ) {
  412.                 close( fd ) ;
  413.                 perror( "setsockopt TTL" ) ;
  414.                 return( -1 ) ;
  415.                 }
  416.  
  417.             if( setsockopt( fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
  418.                             sizeof(loop) )) {
  419.                 close( fd ) ;
  420.                 perror( "setsockopt LOOP" ) ;
  421.                 return( -1 ) ;
  422.                 }
  423.  
  424.             addr->sin_addr = grpaddr;
  425.             break ;
  426.  
  427.         case 'r' :
  428.             /* 
  429.              * Allow multiple instances of this program to listen on the same
  430.              * port on the same host. By default only 1 program can bind
  431.              * to the port on a host.
  432.              */
  433.             on = 1;
  434. //            if( setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, &on,
  435.             if( setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, &on,
  436.                             sizeof(on) ) < 0 ) {
  437.                 close( fd ) ;
  438.                 perror( "setsockopt REUSEPORT" ) ;
  439.                 return( -1 ) ;
  440.                 }
  441.  
  442.             if( bind( fd, addr, sizeof(*addr) ) < 0 ) {
  443.                 close( fd ) ;
  444.                 perror( "bind" ) ;
  445.                 return( -1 ) ;
  446.                 }
  447.  
  448.             mreq.imr_multiaddr = grpaddr;
  449.             mreq.imr_interface = ifaddr;
  450.             if( setsockopt( fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  451.                             &mreq, sizeof(mreq) ) < 0 ) {
  452.                 close( fd ) ;
  453.                 perror( "setsockopt ADD" ) ;
  454.                 return( -1 ) ;
  455.                 }
  456.             break ;
  457.  
  458.         }
  459.  
  460.     return( fd ) ;
  461. }
  462.  
  463.  
  464.  
  465. /* 
  466.  * Make sure the specified interface exists and is capable of doing
  467.  * multicasting.
  468.  */
  469. static int checkInterface(
  470.     const char *interface,
  471.     int fd,
  472.     char mode,
  473.     struct in_addr *ifaddr
  474.     )
  475. {
  476.     int                i ;
  477.     struct ifconf    ifc ;
  478.     struct ifreq    *ifr ;
  479.     char            buf[BUFSIZ] ;
  480.  
  481.     ifc.ifc_len = sizeof( buf ) ;
  482.     ifc.ifc_buf = buf ;
  483.     if( ioctl( fd, SIOCGIFCONF, (char *) &ifc ) < 0 ) {
  484.         perror( "ioctl SIOCGIFCONF" ) ;
  485.         return( -1 ) ;
  486.         }
  487.  
  488.     ifr = ifc.ifc_req;
  489.     for( i = ifc.ifc_len/sizeof(*ifr) ; --i >= 0 ; ifr++ ) {
  490.         if( ifr->ifr_addr.sa_family != AF_INET )
  491.             continue ;
  492.  
  493.         if( strncmp( ifr->ifr_name, interface, strlen( ifr->ifr_name ) )
  494.             == 0 ) {
  495.             /* Obtain the interface's assigned network address */
  496.             *ifaddr = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr ;
  497.  
  498.             if( ioctl( fd, SIOCGIFFLAGS, (char *) ifr ) < 0 ) {
  499.                 perror( "ioctl SIOCGIFFLAGS" ) ;
  500.                 return( -1 ) ;
  501.                 }
  502.             if( !( ifr->ifr_flags & IFF_MULTICAST ) ) {
  503.                 fprintf( stderr, "%s: interface doesn't support multicasting\n",
  504.                         interface ) ;
  505.                 return( -1 ) ;
  506.                 }
  507.  
  508.             /* Specify the interface to use when sending packets */
  509.             if( mode == 'w' && setsockopt( fd, IPPROTO_IP, IP_MULTICAST_IF,
  510.                 ifaddr, sizeof(*ifaddr) ) < 0 ) {
  511.                 perror( "setsockopt MULTICAST" ) ;
  512.                 return( -1 ) ;
  513.                 }
  514.             break;
  515.             }
  516.         }
  517.  
  518.     if( ifaddr->s_addr == INADDR_ANY ) {
  519.         fprintf(stderr, "%s: invalid or unknown interface\n", interface);
  520.         return( -1 ) ;
  521.         }
  522.  
  523.     return( 0 ) ;
  524. }
  525.